أطلق العنان لتطوير واجهات برمجة تطبيقات قوية باستخدام FastAPI و Pydantic. تعلم كيفية تنفيذ التحقق التلقائي والقوي من صحة الطلبات، ومعالجة الأخطاء، وبناء تطبيقات قابلة للتطوير.
إتقان التحقق من صحة طلبات FastAPI باستخدام نماذج Pydantic: دليل شامل
في عالم تطوير الويب الحديث، يعتبر بناء واجهات برمجة تطبيقات قوية وموثوقة أمرًا بالغ الأهمية. أحد المكونات الأساسية لهذه المتانة هو التحقق من صحة البيانات. بدونه، تكون عرضة للمبدأ القديم "مدخلات خاطئة، مخرجات خاطئة"، مما يؤدي إلى أخطاء، وثغرات أمنية، وتجربة مطور سيئة لمستهلكي واجهة برمجة التطبيقات الخاصة بك. هذا هو المكان الذي يتألق فيه المزيج القوي من FastAPI و Pydantic، مما يحول ما كان مهمة شاقة إلى عملية أنيقة وتلقائية.
اكتسب FastAPI، وهو إطار عمل ويب بايثون عالي الأداء، شعبية هائلة لسرعته وبساطته وميزاته سهلة الاستخدام للمطورين. يكمن في قلب سحره تكامل عميق مع Pydantic، وهي مكتبة لإدارة التحقق من صحة البيانات والإعدادات. معًا، يوفران طريقة سلسة وآمنة من حيث الأنواع وذاتية التوثيق لبناء واجهات برمجة التطبيقات.
سيأخذك هذا الدليل الشامل في رحلة عميقة لاستخدام نماذج Pydantic للتحقق من صحة الطلبات في FastAPI. سواء كنت مبتدئًا بدأت للتو في استخدام واجهات برمجة التطبيقات أو مطورًا ذا خبرة تتطلع إلى تبسيط سير عملك، فستجد رؤى قابلة للتنفيذ وأمثلة عملية لإتقان هذه المهارة الأساسية.
لماذا يعد التحقق من صحة الطلبات أمرًا بالغ الأهمية لواجهات برمجة التطبيقات الحديثة؟
قبل أن ننتقل إلى التعليمات البرمجية، دعنا نحدد سبب كون التحقق من صحة الإدخال ليس مجرد ميزة "مستحسنة" - بل هو ضرورة أساسية. يخدم التحقق السليم من صحة الطلبات العديد من الوظائف الهامة:
- سلامة البيانات: يضمن أن البيانات التي تدخل نظامك تتوافق مع البنية والأنواع والقيود المتوقعة. يمنع هذا البيانات المشوهة من إتلاف قاعدة البيانات الخاصة بك أو التسبب في سلوك غير متوقع للتطبيق.
- الأمان: من خلال التحقق من صحة جميع البيانات الواردة وتعقيمها، فإنك تنشئ خط الدفاع الأول ضد التهديدات الأمنية الشائعة مثل حقن NoSQL/SQL، والبرمجة النصية عبر المواقع (XSS)، والهجمات الأخرى المستندة إلى الحمولة.
- تجربة المطور (DX): بالنسبة لمستهلكي واجهة برمجة التطبيقات (بما في ذلك فرق الواجهة الأمامية الخاصة بك)، فإن الملاحظات الواضحة والفورية حول الطلبات غير الصالحة لا تقدر بثمن. بدلاً من خطأ عام في الخادم 500، ترجع واجهة برمجة تطبيقات تم التحقق من صحتها جيدًا خطأ 422 دقيقًا، مع تفصيل الحقول الخاطئة بالضبط وسبب ذلك.
- المتانة والموثوقية: يمنع التحقق من صحة البيانات عند نقطة الدخول في تطبيقك البيانات غير الصالحة من الانتشار في عمق منطق عملك. هذا يقلل بشكل كبير من فرص حدوث أخطاء وقت التشغيل ويجعل قاعدة التعليمات البرمجية الخاصة بك أكثر قابلية للتنبؤ وأسهل في التصحيح.
الثنائي القوي: FastAPI و Pydantic
إن التآزر بين FastAPI و Pydantic هو ما يجعل الإطار مقنعًا للغاية. دعنا نحلل أدوارهم:
- FastAPI: إطار عمل ويب حديث يستخدم تلميحات أنواع بايثون القياسية لتحديد معلمات واجهة برمجة التطبيقات ونصوص الطلبات. إنه مبني على Starlette للأداء العالي و ASGI للقدرات غير المتزامنة.
- Pydantic: مكتبة تستخدم نفس تلميحات أنواع بايثون لإجراء التحقق من صحة البيانات، والتسلسل (تحويل البيانات من وإلى تنسيقات مثل JSON)، وإدارة الإعدادات. أنت تحدد "شكل" بياناتك كفئة ترث من `BaseModel` الخاص بـ Pydantic.
عندما تستخدم نموذج Pydantic للإعلان عن نص طلب في عملية مسار FastAPI، فإن الإطار ينظم تلقائيًا ما يلي:
- يقرأ نص طلب JSON الوارد.
- يقوم بتحليل JSON ويمرر البيانات إلى نموذج Pydantic الخاص بك.
- Pydantic يتحقق من صحة البيانات مقابل الأنواع والقيود المحددة في النموذج الخاص بك.
- إذا كان صالحًا، فإنه ينشئ مثيلًا للنموذج الخاص بك، مما يمنحك كائن بايثون مكتوبًا بالكامل للعمل به في وظيفتك، مع الإكمال التلقائي الكامل في محرر النصوص الخاص بك.
- إذا كان غير صالح، فإن FastAPI يلتقط `ValidationError` الخاص بـ Pydantic ويعيد تلقائيًا استجابة JSON مفصلة مع رمز حالة HTTP 422 كيان غير قابل للمعالجة.
- يقوم بإنشاء مخطط JSON تلقائيًا من نموذج Pydantic الخاص بك، والذي يستخدم لتشغيل وثائق واجهة برمجة التطبيقات التفاعلية (Swagger UI و ReDoc).
يزيل سير العمل الآلي هذا التعليمات البرمجية النمطية، ويقلل الأخطاء، ويحافظ على تعريفات البيانات وقواعد التحقق من الصحة والتوثيق متزامنة تمامًا.
البدء: التحقق الأساسي من صحة نص الطلب
دعونا نرى هذا عمليًا مع مثال بسيط. تخيل أننا نبني واجهة برمجة تطبيقات لمنصة تجارة إلكترونية ونحتاج إلى نقطة نهاية لإنشاء منتج جديد.
أولاً، حدد شكل بيانات المنتج الخاص بك باستخدام نموذج Pydantic:
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional
# 1. Define the Pydantic model
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
app = FastAPI()
# 2. Use the model in a path operation
@app.post("/items/")
async def create_item(item: Item):
# At this point, 'item' is a validated Pydantic model instance
item_dict = item.dict()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({"price_with_tax": price_with_tax})
return item_dict
ماذا يحدث هنا؟
في وظيفة `create_item`، قمنا بتلميح نوع المعلمة `item` كنموذج Pydantic الخاص بنا، `Item`. هذه هي الإشارة إلى FastAPI لإجراء التحقق من الصحة.
طلب صالح:
إذا أرسل عميل طلب POST إلى `/items/` بنص JSON صالح، مثل هذا:
{
"name": "Super Gadget",
"price": 59.99,
"tax": 5.40
}
سيتحقق FastAPI و Pydantic بنجاح من صحته. داخل وظيفة `create_item` الخاصة بك، سيكون `item` مثيلًا لفئة `Item`. يمكنك الوصول إلى بياناته باستخدام تدوين النقطة (على سبيل المثال، `item.name`، `item.price`)، وسيوفر IDE الخاص بك الإكمال التلقائي الكامل. ستعيد واجهة برمجة التطبيقات استجابة 200 OK مع البيانات المعالجة.
طلب غير صالح:
الآن، دعونا نرى ما يحدث إذا أرسل العميل طلبًا مشوهًا، على سبيل المثال، إرسال السعر كسلسلة بدلاً من قيمة عائمة:
{
"name": "Faulty Gadget",
"price": "ninety-nine"
}
لست بحاجة إلى كتابة عبارة `if` واحدة أو كتلة `try-except`. يلتقط FastAPI تلقائيًا خطأ التحقق من الصحة من Pydantic ويعيد استجابة HTTP 422 المفصلة بشكل جميل هذه:
{
"detail": [
{
"loc": [
"body",
"price"
],
"msg": "value is not a valid float",
"type": "type_error.float"
}
]
}
رسالة الخطأ هذه مفيدة بشكل لا يصدق للعميل. إنه يخبرهم بالموقع الدقيق للخطأ (`body` -> `price`) ورسالة قابلة للقراءة البشرية ونوع خطأ قابل للقراءة آليًا. هذه هي قوة التحقق التلقائي.
التحقق المتقدم من صحة Pydantic في FastAPI
مجرد التحقق من النوع الأساسي هو مجرد البداية. يقدم Pydantic مجموعة غنية من الأدوات لقواعد التحقق من الصحة الأكثر تعقيدًا، والتي تتكامل جميعها بسلاسة مع FastAPI.
قيود الحقول والتحقق من الصحة
يمكنك فرض قيود أكثر تحديدًا على الحقول باستخدام وظيفة `Field` من Pydantic (أو `Query`، `Path`، `Body` من FastAPI، وهي فئات فرعية من `Field`).
لنقم بإنشاء نموذج تسجيل مستخدم مع بعض قواعد التحقق من الصحة الشائعة:
from pydantic import BaseModel, Field, EmailStr
class UserRegistration(BaseModel):
username: str = Field(
...,
min_length=3,
max_length=50,
regex="^[a-zA-Z0-9_]+$"
)
email: EmailStr # Pydantic has built-in types for common formats
password: str = Field(..., min_length=8)
age: Optional[int] = Field(
None,
gt=0,
le=120,
description="The age must be a positive integer."
)
@app.post("/register/")
async def register_user(user: UserRegistration):
return {"message": f"User {user.username} registered successfully!"}
في هذا النموذج:
- يجب أن يكون `username` بين 3 و 50 حرفًا ويمكن أن يحتوي فقط على أحرف وأرقام وشرطات سفلية.
- يتم التحقق من صحة `email` تلقائيًا للتأكد من أنه تنسيق بريد إلكتروني صالح باستخدام `EmailStr`.
- يجب أن يكون `password` 8 أحرف على الأقل.
- يجب أن يكون `age`، إذا تم توفيره، أكبر من 0 (`gt`) وأقل من أو يساوي 120 (`le`).
- تشير `...` (علامة الحذف) كوسيطة أولى لـ `Field` إلى أن الحقل مطلوب.
نماذج متداخلة
غالبًا ما تتعامل واجهات برمجة التطبيقات الواقعية مع كائنات JSON معقدة ومتداخلة. يتعامل Pydantic مع هذا بأناقة من خلال السماح لك بتضمين النماذج داخل نماذج أخرى.
from typing import List
class Tag(BaseModel):
id: int
name: str
class Article(BaseModel):
title: str
content: str
tags: List[Tag] = [] # A list of other Pydantic models
author_id: int
@app.post("/articles/")
async def create_article(article: Article):
return article
عندما يتلقى FastAPI طلبًا لنقطة النهاية هذه، فإنه يتحقق من صحة الهيكل المتداخل بأكمله. سيضمن أن `tags` عبارة عن قائمة، وأن كل عنصر داخل تلك القائمة هو كائن `Tag` صالح (أي أنه يحتوي على عدد صحيح `id` وسلسلة `name`).
التحقق من الصحة المخصص
بالنسبة لمنطق الأعمال الذي لا يمكن التعبير عنه بالقيود القياسية، يوفر Pydantic مصمم `@validator`. يتيح لك هذا كتابة وظائف التحقق من الصحة الخاصة بك.
أحد الأمثلة الكلاسيكية هو تأكيد حقل كلمة المرور:
from pydantic import BaseModel, Field, validator
class PasswordChangeRequest(BaseModel):
new_password: str = Field(..., min_length=8)
confirm_password: str
@validator('confirm_password')
def passwords_match(cls, v, values, **kwargs):
# 'v' is the value of 'confirm_password'
# 'values' is a dict of the fields already processed
if 'new_password' in values and v != values['new_password']:
raise ValueError('Passwords do not match')
return v
@app.put("/user/password")
async def change_password(request: PasswordChangeRequest):
# Logic to change the password...
return {"message": "Password updated successfully"}
إذا فشل التحقق من الصحة (أي أن الدالة تثير `ValueError`)، فإن Pydantic يلتقطها ويحولها FastAPI إلى استجابة خطأ 422 قياسية، تمامًا كما هو الحال مع قواعد التحقق من الصحة المضمنة.
التحقق من صحة أجزاء الطلب المختلفة
في حين أن نصوص الطلبات هي حالة الاستخدام الأكثر شيوعًا، إلا أن FastAPI تستخدم نفس مبادئ التحقق من الصحة لأجزاء أخرى من طلب HTTP.
معلمات المسار والاستعلام
يمكنك إضافة التحقق المتقدم من الصحة إلى معلمات المسار والاستعلام باستخدام `Path` و `Query` من `fastapi`. تعمل هذه تمامًا مثل `Field` الخاص بـ Pydantic.
from fastapi import FastAPI, Path, Query
from typing import List
app = FastAPI()
@app.get("/search/")
async def search(
q: str = Query(..., min_length=3, max_length=50, description="Your search query"),
tags: List[str] = Query([], description="Tags to filter by")
):
return {"query": q, "tags": tags}
@app.get("/files/{file_id}")
async def get_file(
file_id: int = Path(..., gt=0, description="The ID of the file to retrieve")
):
return {"file_id": file_id}
إذا حاولت الوصول إلى `/files/0`، فسيعيد FastAPI خطأ 422 لأن `file_id` يفشل في التحقق من صحة `gt=0` (أكبر من 0). وبالمثل، سيفشل طلب إلى `/search/?q=ab` في قيد `min_length=3`.
التعامل مع أخطاء التحقق من الصحة بأمان
تعتبر استجابة الخطأ 422 الافتراضية لـ FastAPI ممتازة، ولكن في بعض الأحيان تحتاج إلى تخصيصها لتناسب معيارًا محددًا أو لإضافة تسجيل إضافي. تجعل FastAPI هذا الأمر سهلاً من خلال نظام معالجة الاستثناءات الخاص به.
يمكنك إنشاء معالج استثناء مخصص لـ `RequestValidationError`، وهو نوع الاستثناء المحدد الذي تثيره FastAPI عندما يفشل التحقق من صحة Pydantic.
from fastapi import FastAPI, Request, status
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
# You can log the error details here
# print(exc.errors())
# print(exc.body)
# Customize the response format
custom_errors = []
for error in exc.errors():
custom_errors.append(
{
"field": ".".join(str(loc) for loc in error["loc"]),
"message": error["msg"],
"type": error["type"]
}
)
return JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"error": "Validation Failed", "details": custom_errors},
)
# Add an endpoint that can fail validation
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
async def create_item(item: Item):
return item
باستخدام هذا المعالج، سيتلقى الطلب غير الصالح الآن استجابة 400 Bad Request مع هيكل JSON المخصص الخاص بك، مما يمنحك التحكم الكامل في تنسيق الخطأ الذي تعرضه واجهة برمجة التطبيقات الخاصة بك.
أفضل الممارسات لنماذج Pydantic في FastAPI
لبناء تطبيقات قابلة للتطوير والصيانة، ضع في اعتبارك أفضل الممارسات هذه:
- حافظ على نماذج DRY (لا تكرر نفسك): استخدم وراثة النموذج لتجنب التكرار. قم بإنشاء نموذج أساسي مع الحقول الشائعة، ثم قم بتوسيعه لحالات استخدام محددة مثل الإنشاء (الذي قد يحذف حقول `id` و `created_at`) والقراءة (الذي يتضمن جميع الحقول).
- افصل نماذج الإدخال والإخراج: غالبًا ما تختلف البيانات التي تقبلها كمدخلات (`POST`/`PUT`) عن البيانات التي ترجعها (`GET`). على سبيل المثال، يجب ألا ترجع أبدًا تجزئة كلمة مرور المستخدم في استجابة واجهة برمجة التطبيقات. استخدم المعلمة `response_model` في مصمم عملية المسار لتحديد نموذج Pydantic محدد للإخراج، مما يضمن عدم الكشف عن البيانات الحساسة عن طريق الخطأ.
- استخدم أنواع بيانات محددة: استفد من المجموعة الغنية من الأنواع الخاصة في Pydantic مثل `EmailStr` و `HttpUrl` و `UUID` و `datetime` و `date`. توفر التحقق المدمج من الصحة للتنسيقات الشائعة، مما يجعل نماذجك أكثر قوة وتعبيرًا.
- قم بتكوين النماذج باستخدام فئة `Config`: يمكن تخصيص نماذج Pydantic عبر فئة `Config` داخلية. أحد الإعدادات الرئيسية لتكامل قاعدة البيانات هو `from_attributes=True` (المعروف سابقًا باسم `orm_mode=True` في Pydantic v1)، والذي يسمح بملء النموذج من كائنات ORM (مثل تلك الموجودة في SQLAlchemy أو Tortoise ORM) عن طريق الوصول إلى السمات بدلاً من مفاتيح القاموس.
الخلاصة
إن التكامل السلس لـ Pydantic هو بلا شك أحد الميزات القاتلة لـ FastAPI. إنه يرفع من تطوير واجهة برمجة التطبيقات من خلال أتمتة المهام الحاسمة ولكن غالبًا ما تكون شاقة للتحقق من صحة البيانات والتسلسل والتوثيق. من خلال تحديد أشكال البيانات الخاصة بك مرة واحدة باستخدام نماذج Pydantic، فإنك تكتسب ثروة من الفوائد: أمان قوي، وتحسين سلامة البيانات، وتجربة مطور فائقة لمستهلكي واجهة برمجة التطبيقات الخاصة بك، وقاعدة تعليمات برمجية أكثر قابلية للصيانة لنفسك.
من خلال نقل منطق التحقق من الصحة من كود عملك إلى نماذج بيانات تعريفية، فإنك تنشئ واجهات برمجة تطبيقات ليست سريعة التشغيل فحسب، بل سريعة البناء أيضًا، وسهلة الفهم، وآمنة للاستخدام. لذلك، في المرة القادمة التي تبدأ فيها مشروع واجهة برمجة تطبيقات بايثون جديدًا، احتضن قوة FastAPI و Pydantic لإنشاء خدمات ذات درجة احترافية حقًا.